package com.gitee.srurl.core.util;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gitee.srurl.core.cache.record.ShortUrlCacheManager;
import com.gitee.srurl.core.constant.RedisConstant;
import com.gitee.srurl.core.domain.SucUrlRecordDomain;
import com.gitee.srurl.core.dto.result.ShortUrlResultDTO;
import com.gitee.srurl.core.exception.ServiceException;
import com.gitee.srurl.core.properties.IdGenProperties;
import com.gitee.srurl.core.service.ISucUrlRecordService;
import com.gitee.srurl.core.util.redis.RedisValueUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Optional;
import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author zxw
 * @date 2023/5/3 22:01
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Component
public class RedisCacheUtil {

    private static final ShortUrlCacheManager shortUrlCacheManager = SpringContextUtil.getBean(ShortUrlCacheManager.class);

    private static final ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = SpringContextUtil.getBean("scheduledThreadPoolExecutor");

    private static final IdGenProperties idGenProperties = SpringContextUtil.getBean(IdGenProperties.class);

    private static final ISucUrlRecordService sucUrlRecordService = SpringContextUtil.getBean(ISucUrlRecordService.class);

    public static ShortUrlResultDTO getCache(String shortId) {
        return shortUrlCacheManager.getCache(shortId);
    }

    public static void putCache(String shortId, ShortUrlResultDTO shortUrlResultDTO) {
        shortUrlCacheManager.putCache(shortId, shortUrlResultDTO);
    }

    public static void putCacheIfAbsent(String shortId, ShortUrlResultDTO shortUrlResultDTO) {
        shortUrlCacheManager.putCacheIfAbsent(shortId, shortUrlResultDTO);
    }

    public static void removeCache(String shortId) {
        shortUrlCacheManager.removeCache(shortId);
        boolean openDoubleCheck = Optional.ofNullable(idGenProperties.getDoubleDuplicateDetection().getOpen()).orElse(false);
        if (openDoubleCheck) {
            // 如果设置双重检测 设置缓存
            LambdaQueryWrapper<SucUrlRecordDomain> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SucUrlRecordDomain::getShortId, shortId);
            SucUrlRecordDomain urlRecordDomain = sucUrlRecordService.getOne(wrapper);
            if (urlRecordDomain != null) {
                RedisValueUtil.delete(RedisConstant.Cache.DOUBLE_DUPLICATE_CACHE + urlRecordDomain.getOriginUrl());
            }
        }
    }

    /**
     * 默认延迟1.5s后删除
     * todo 这个延迟删除真正使用有很多问题（强停、事务、网络波动等很多情况都会导致这边出问题）  因为依赖的少就先这样子处理
     *  如果需要使用需要接入其他线上项目已存在的保证双写一致性的逻辑
     *
     * @param shortId     短链ID
     * @param delayRemove 是否延迟删除
     */
    public static void removeCache(String shortId, boolean delayRemove) {
        if (delayRemove) {
            scheduledThreadPoolExecutor.schedule(new TimerTask() {
                @Override
                public void run() {
                    removeCache(shortId);
                }
            }, 1500, TimeUnit.MILLISECONDS);
        } else {
            removeCache(shortId);
        }
    }

    public static void removeCache(String shortId, long delay, TimeUnit unit) {

        if (delay < 0 || unit == null) {
            throw new ServiceException("延迟消息，延迟时间参数错误！");
        }

        scheduledThreadPoolExecutor.schedule(new TimerTask() {
            @Override
            public void run() {
                removeCache(shortId);
            }
        }, delay, unit);
    }

    public static boolean containsCache(String shortId) {
        return shortUrlCacheManager.containsCache(shortId);
    }
}
